﻿//-----------------------------------------------------------------------
// <copyright file="Cell.cs" company="cx studio">
//     Copyright (c) cx studio. All rights reserved.
// </copyright>
// <author>Xi Chen</author>
//-----------------------------------------------------------------------
namespace CentralFoveaLib.Brain
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    /// <summary>
    /// 现在这套系统我认为的主体思想是：我们的这些感知是由神经系统与激素共同完成的。
    /// 这里只涉及神经系统的部分。
    /// 我认为神经系统的运行背后的原理：
    /// 1.每个细胞都有自己的独立运行机制
    /// 2.由细胞群完成一次神经活动
    /// 3.细胞会对连接信号进行一次X,一次Y方向的统计,这样他就可以区分哪些是
    /// 4.细胞有分化，至少我已知有两种
    /// 5.通过当前细胞可以决定谁是最优的传入链接，通过去除劣势策略，去掉没用的连接
    /// </summary>
    public class Cell
    {
        ///// <summary>
        ///// 单元的名字
        ///// </summary>
        //public String Name { get; set; }
        public Cell() { }

        /// <summary>
        /// 表示自己的函数
        /// </summary>
        public int[] XAxis { get; set; }
        /// <summary>
        /// 表示自己的函数
        /// </summary>
        public int[] YAxis { get; set; }

        public int[] XAxisRate
        {
            get
            {
                return Scale(ChangeToPercent(this.XAxis), 100);
            }
        }

        public int[] YAxisRate
        {
            get
            {
                return Scale(ChangeToPercent(this.YAxis), 100);
            }
        }

        public bool IsBlock()
        {
            if (XAxisRate[0] == 0 && YAxisRate[0] == 0 && XAxisRate[XAxisRate.Length - 1] == 0 && YAxisRate[YAxisRate.Length - 1] == 0)
                return true;

            return false;
        }

        public void Print()
        {
            int[] row = new int[YAxis.Length];
            int[] col = new int[XAxis.Length];

            int[] row2 = new int[YAxis.Length];
            int[] col2 = new int[XAxis.Length];

            Array.Copy(YAxis, row, YAxis.Length);
            Array.Copy(XAxis, col, XAxis.Length);

            //int[][] c = new int[row.Length][];
            for (int i = 0; i < row.Length; i++)
            {
                //c[i] = new int[col.Length];
                int rowItem = row[i];

                for (int j = 0; j < col.Length; j++)
                {
                    int colItem = col[j];
                    if (rowItem > 0 && colItem > 0)
                    {
                        //找出最大的，然后减1
                        int maxValue = colItem;
                        int maxValueIndex = j;
                        for (int k = 0; k < col.Length; k++)
                        {
                            int colItem2 = col[k];
                            if (colItem2 > maxValue)
                            {
                                maxValue = colItem2;
                                maxValueIndex = k;
                            }
                        }

                        if (maxValueIndex == j)
                        {
                            Debug.Write(1);
                            col[maxValueIndex]--;
                            rowItem--;
                            row[i]--;
                        }
                        else
                        {
                            Debug.Write(0);
                        }
                    }
                    else
                    {
                        Debug.Write(0);
                    }
                }

                Debug.Write("\n");
            }

        }

        public Cell Compress()
        {
            Cell cell = new Cell();
            int left = 0;
            int right = 0;
            int top = 0;
            int bottom = 0;
            for (int i = 0; i < XAxis.Length; i++)
            {
                var xt = XAxis[i];
                if (xt != 0 )
                {
                    cell.X = X + i;
                    left = i;
                    break;
                }
            }
            for (int i = XAxis.Length - 1; i > 0; i--)
            {
                var xt = XAxis[i];
                if (xt != 0)
                {
                    right = i;
                    break;
                }
            }

            for (int i = 0; i < YAxis.Length; i++)
            {
                var yt = YAxis[i];
                if (yt != 0)
                {
                    cell.Y = X + i;
                    top = i;
                    break;
                }
            }
            for (int i = YAxis.Length - 1; i > 0; i--)
            {
                var yt = YAxis[i];
                if (yt != 0)
                {
                    bottom = i;
                    break;
                }
            }


            if (left == 0 && right == 0 && top ==0 && bottom ==0)
                return this;

            int[] xArr = new int[right - left + 1];
            int[] yArr = new int[bottom -top + 1];
            int k = 0;
            for (int i = left; i <= right; i++)
            {
                xArr[k] = XAxis[i];
                k++;
            }
            k = 0;
            for (int i = top; i <= bottom; i++)
            {
                yArr[k] = YAxis[i];
                k++;
            }

            cell.XAxis = xArr;
            cell.YAxis = yArr;
            return cell;
        }

        /// <summary>
        /// 输出
        /// </summary>
        //public int Output { get; set; }
        //public int[] Output { get; set; }


        // public int[] OutputY { get; set; }

        //public List<Cell> XCells { get; set; }
        //public List<Cell> YCells { get; set; }

        //public Cell[][] Flag { get; set; }

        public int X { get; set; }
        public int Y { get; set; }

        public decimal IsSame(Cell cell)
        {
            //判断X,y轴的相似程度

            decimal xDiff = CheckAix(XAxis, cell.XAxis);
            decimal yDiff = CheckAix(YAxis, cell.YAxis);
            return (xDiff + yDiff) / 2;
        }
        private int CheckAix(int[] a, int[] b)
        {
            int diff = 0;
            int cDiff = 10;
            int[] aL = ChangeToPercent(a);
            int[] bL = ChangeToPercent(b);
            if (a.Length > b.Length)
            {
                aL = Scale(aL, b.Length);
            }
            else if (a.Length < b.Length)
            {
                bL = Scale(bL, a.Length);
            }


            for (int i = 0; i < aL.Length; i++)
            {
                if (Math.Abs(aL[i] - bL[i]) < cDiff) { diff += 1; }
            }

            return (diff / aL.Length) * 10;
        }

        private int[] Scale(int[] a, int l)
        {
            int[] temp = new int[l];
            int time = a.Length / l;
            for (int i = 0; i < temp.Length; i++)
            {
                temp[i] = a[time * i];
            }
            return temp;
        }

        private int[] ChangeToPercent(int[] a)
        {
            int[] yRate = new int[a.Length];
            int max = 0;
            for (int i = 0; i < a.Length; i++)
            {
                max = Math.Max(max, a[i]);
            }
            for (int i = 0; i < a.Length; i++)
            {
                if (max > 0)
                {
                    yRate[i] = (a[i] / max) * 100;
                }
            }
            return yRate;
        }

        public void AddCell(Cell cell)
        {
            int startX = X;
            int endX = X + XAxis.Length;
            if (cell.X < X)
            {
                startX = cell.X;
            }

            if (cell.X + XAxis.Length > endX)
            {
                endX = cell.X + XAxis.Length;
            }
            int[] xList = new int[endX - startX + 1];
            for (int i = 0; i < xList.Length; i++)
            {
                if (startX <= (X + i) && (X + i) < (X + XAxis.Length))
                {
                    xList[i] += XAxis[i];
                }
                if (startX <= (cell.X + i) && (cell.X + i) < (cell.X + XAxis.Length))
                {
                    xList[i] += XAxis[i];
                }
            }


            int startY = Y;
            int endY = Y + YAxis.Length;
            if (cell.Y < Y)
            {
                startY = cell.Y;
            }

            if (cell.Y + YAxis.Length > endY)
            {
                endY = cell.Y + YAxis.Length;
            }
            int[] yList = new int[endY - startY + 1];
            for (int i = 0; i < yList.Length; i++)
            {
                if (startY <= (Y + i) && (Y + i) < (Y + YAxis.Length))
                {
                    yList[i] += YAxis[i];
                }
                if (startY <= (cell.Y + i) && (cell.Y + i) < (cell.Y + YAxis.Length))
                {
                    yList[i] += YAxis[i];
                }
            }
           

            if (cell.Y < Y)
            {
                Y = cell.Y;
            }

            this.X = startX;
            this.Y = startY;
            this.XAxis = xList;
            this.YAxis = yList;
        }
    }
}
